在前一篇文章中,我們介紹了怎麼在 Effect 中處理錯誤,然而,目前我們拋出的錯誤型態只有 Error
,說好的一看 type 就能知道會發生什麼錯誤呢?在這篇文章中,我們要看 Effect 中的第一個資料型態的函式庫,並用它來建立自訂的錯誤類型
在開始之前,我們先來看看一般要建立自訂的錯誤類型要怎麼做,這在 MDN 其實就有個範例
class MyError extends Error {
// 這邊是原本 Error 傳入的參數,你也可以傳入自訂的參數來擴充自訂的 error 的屬性
// 但不論如何,都還是建議要可以傳入 ErrorOptions 中的 cause ,以連結到原始的錯誤
constructor(message: string, options: ErrorOptions) {
// 呼叫 super 初始化
super(message, options)
this.name = 'MyError' // 設定 error 的名稱
if (Error.captureStackTrace) {
// 確保 error 的 constructor 本身不會出現在 stack trace
Error.captureStackTrace(this, MyError);
}
// 你可以設定其它屬性以提供更多的資訊
}
}
說簡單也不簡單,複雜到也還好,但… 如果每個自訂的 error 都要寫一次這些其實有點麻煩
在 Effect 中,你可以使用 Data.Error
或是 Data.TaggedError
來建立 error ,就像這樣
import { Data } from 'effect'
// 我們可以在 Data.Error 的 generic 參數中設定這個 error 要接受哪些屬性
// 推薦加上 `cause`
class ValidationError extends Data.Error<{message: string, data?: unknown, cause?: unknown}> {}
就這樣,恭喜你有個自訂的 error 了,使用時就像這樣
new ValidationError({
message: 'input validation fail',
data: { userInput: 'invalid data' },
cause: new Error('your original error'),
})
如果搭配 Effect.try
大概會是這種感覺
// 假設我們用 zod 來驗證資料
import { z } from 'zod'
const dataSchema = z.object({ data: z.string() })
Effect.try({
try: () => dataSchema.parse(userData),
catch: (error) => new ValidationError({
message: 'input validation fail',
data: userData,
cause: error,
})
})
Data.TaggedError
與 Effect.catchTag*
在 Data 中,還有一個 TaggedError
,用法也很類似
// 差別在於這邊要傳入一個 error 的名字
class ValidationError extends Data.TaggedError('ValidationError')<{
message: string
data?: unknown
cause?: unknown
}> {}
這個跟 Data.Error
的差別是,建出來的 error 會多一個 _tag
的屬性,屬性會是你設定的名字 ValidationError
,這在 Effect 中是一種很常見的 pattern ,我們可以使用 Effect.catchTag
或是 Effect.catchTags
來捕捉帶有特定的 _tag
的錯誤
pipe(
Effect.fail(new ValidationError({ message: 'error' })),
Effect.catchTag('ValidationError', (error) => {
console.error(error)
return Effect.void
}),
)
// 或是使用 catchTags 一次處理多個 error
pipe(
Effect.fail(new ValidationError({ message: 'error' })),
Effect.catchTags({
ValidationError: (error) => {
console.error(error)
return Effect.void
},
}),
)
這邊我們真正的認識了 Effect 中的一個資料型態,雖然之前也有出現過一個 Either
不過並沒有很完整的介紹,其實 Data
的功能還不只這樣,有機會之後再來介紹,下一次我們來看一個實際的 Effect 的使用案例